using Microsoft.Data.Sqlite;
using Microsoft.Web.Administration;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

public class IISCollector
{
    private readonly string dbPath = "iis_services.db";

    public IISCollector()
    {
        InitializeDatabase();
    }

    public async Task<List<IISServiceInfo>> CollectIISServices(IProgress<string> progress)
    {
        var services = new List<IISServiceInfo>();
        
        try
        {
            progress.Report("开始采集IIS服务信息...");
            
            // 检查是否以管理员权限运行
            if (!IsRunningAsAdministrator())
            {
                throw new UnauthorizedAccessException("需要管理员权限才能访问IIS配置。请以管理员身份运行程序。");
            }
            
            using var serverManager = new ServerManager();
            
            foreach (var site in serverManager.Sites)
            {
                try
                {
                    var serviceInfo = new IISServiceInfo
                    {
                        SiteName = site.Name,
                        SiteId = site.Id,
                        State = site.State.ToString(),
                        PhysicalPath = GetPhysicalPath(site),
                        Bindings = GetBindings(site),
                        ApplicationPool = GetApplicationPool(site),
                        CollectedTime = DateTime.Now
                    };
                    
                    services.Add(serviceInfo);
                    progress.Report($"采集到站点: {site.Name}");
                }
                catch (Exception siteEx)
                {
                    progress.Report($"采集站点 {site.Name} 时出错: {siteEx.Message}");
                    // 继续处理其他站点
                }
            }
            
            await SaveToDatabase(services);
            progress.Report($"采集完成，共采集到 {services.Count} 个IIS站点");
        }
        catch (UnauthorizedAccessException ex)
        {
            Logger.LogError($"IIS服务采集权限错误", ex);
            progress.Report($"权限错误: {ex.Message}");
            throw;
        }
        catch (Exception ex)
        {
            Logger.LogError($"IIS服务采集失败", ex);
            progress.Report($"采集失败: {ex.Message}");
            throw;
        }
        
        return services;
    }

    public List<IISServiceInfo> GetStoredServices()
    {
        var services = new List<IISServiceInfo>();
        
        using var connection = new SqliteConnection($"Data Source={dbPath}");
        connection.Open();
        
        var command = connection.CreateCommand();
        command.CommandText = "SELECT * FROM IISServices ORDER BY CollectedTime DESC";
        
        using var reader = command.ExecuteReader();
        while (reader.Read())
        {
            services.Add(new IISServiceInfo
            {
                Id = reader.GetInt32(0),
                SiteName = reader.GetString(1),
                SiteId = reader.GetInt64(2),
                State = reader.GetString(3),
                PhysicalPath = reader.GetString(4),
                Bindings = reader.GetString(5),
                ApplicationPool = reader.GetString(6),
                CollectedTime = DateTime.Parse(reader.GetString(7)),
                CurrentVersion = reader.GetString(8),
                ProductName = reader.GetString(9)
            });
        }
        
        return services;
    }

    private void InitializeDatabase()
    {
        using var connection = new SqliteConnection($"Data Source={dbPath}");
        connection.Open();
        
        var command = connection.CreateCommand();
        command.CommandText = @"
            CREATE TABLE IF NOT EXISTS IISServices (
                Id INTEGER PRIMARY KEY AUTOINCREMENT,
                SiteName TEXT NOT NULL,
                SiteId INTEGER NOT NULL,
                State TEXT NOT NULL,
                PhysicalPath TEXT,
                Bindings TEXT,
                ApplicationPool TEXT,
                CollectedTime TEXT NOT NULL,
                CurrentVersion TEXT DEFAULT '',
                ProductName TEXT DEFAULT ''
            )";
        command.ExecuteNonQuery();
        
        command.CommandText = @"
            CREATE TABLE IF NOT EXISTS Products (
                Id TEXT PRIMARY KEY,
                Name TEXT NOT NULL,
                Type TEXT NOT NULL,
                Path TEXT,
                SiteName TEXT,
                ServiceName TEXT,
                BackupPath TEXT,
                CurrentVersion TEXT,
                ProductName TEXT
            )";
        command.ExecuteNonQuery();
        
        // 添加缺失的列
        try
        {
            command.CommandText = "ALTER TABLE IISServices ADD COLUMN CurrentVersion TEXT DEFAULT ''";
            command.ExecuteNonQuery();
        }
        catch { /* 列已存在 */ }
        
        try
        {
            command.CommandText = "ALTER TABLE IISServices ADD COLUMN ProductName TEXT DEFAULT ''";
            command.ExecuteNonQuery();
        }
        catch { /* 列已存在 */ }
        
        try
        {
            command.CommandText = "ALTER TABLE Products ADD COLUMN ProductName TEXT DEFAULT ''";
            command.ExecuteNonQuery();
        }
        catch { /* 列已存在 */ }
    }

    private async Task SaveToDatabase(List<IISServiceInfo> services)
    {
        using var connection = new SqliteConnection($"Data Source={dbPath}");
        await connection.OpenAsync();
        
        // 清空旧数据
        var deleteCommand = connection.CreateCommand();
        deleteCommand.CommandText = "DELETE FROM IISServices";
        await deleteCommand.ExecuteNonQueryAsync();
        
        // 插入新数据
        foreach (var service in services)
        {
            var insertCommand = connection.CreateCommand();
            insertCommand.CommandText = @"
                INSERT INTO IISServices (SiteName, SiteId, State, PhysicalPath, Bindings, ApplicationPool, CollectedTime, CurrentVersion, ProductName)
                VALUES (@siteName, @siteId, @state, @physicalPath, @bindings, @appPool, @collectedTime, @currentVersion, @productName)";
            
            insertCommand.Parameters.AddWithValue("@siteName", service.SiteName);
            insertCommand.Parameters.AddWithValue("@siteId", service.SiteId);
            insertCommand.Parameters.AddWithValue("@state", service.State);
            insertCommand.Parameters.AddWithValue("@physicalPath", service.PhysicalPath ?? "");
            insertCommand.Parameters.AddWithValue("@bindings", service.Bindings ?? "");
            insertCommand.Parameters.AddWithValue("@appPool", service.ApplicationPool ?? "");
            insertCommand.Parameters.AddWithValue("@collectedTime", service.CollectedTime.ToString("yyyy-MM-dd HH:mm:ss"));
            insertCommand.Parameters.AddWithValue("@currentVersion", service.CurrentVersion);
            insertCommand.Parameters.AddWithValue("@productName", service.ProductName);
            
            await insertCommand.ExecuteNonQueryAsync();
        }
    }

    private string GetPhysicalPath(Site site)
    {
        return site.Applications["/"]?.VirtualDirectories["/"]?.PhysicalPath ?? "";
    }

    private string GetBindings(Site site)
    {
        var bindings = new List<string>();
        foreach (var binding in site.Bindings)
        {
            bindings.Add($"{binding.Protocol}://{binding.BindingInformation}");
        }
        return string.Join("; ", bindings);
    }

    private string GetApplicationPool(Site site)
    {
        try
        {
            return site.Applications["/"]?.ApplicationPoolName ?? "";
        }
        catch
        {
            return "无法获取";
        }
    }
    
    private bool IsRunningAsAdministrator()
    {
        try
        {
            var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
            var principal = new System.Security.Principal.WindowsPrincipal(identity);
            return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
        }
        catch
        {
            return false;
        }
    }

    public void UpdateServiceInfo(string siteName, string productName, string version)
    {
        using var connection = new SqliteConnection($"Data Source={dbPath}");
        connection.Open();
        
        var command = connection.CreateCommand();
        command.CommandText = "UPDATE IISServices SET CurrentVersion = @version, ProductName = @productName WHERE SiteName = @siteName";
        command.Parameters.AddWithValue("@version", version);
        command.Parameters.AddWithValue("@productName", productName);
        command.Parameters.AddWithValue("@siteName", siteName);
        command.ExecuteNonQuery();
    }
    
    public void SaveProduct(Product product)
    {
        using var connection = new SqliteConnection($"Data Source={dbPath}");
        connection.Open();
        
        var command = connection.CreateCommand();
        command.CommandText = @"
            INSERT OR REPLACE INTO Products (Id, Name, Type, Path, SiteName, ServiceName, BackupPath, CurrentVersion, ProductName)
            VALUES (@id, @name, @type, @path, @siteName, @serviceName, @backupPath, @currentVersion, @productName)";
        
        command.Parameters.AddWithValue("@id", product.Id);
        command.Parameters.AddWithValue("@name", product.Name);
        command.Parameters.AddWithValue("@type", product.Type);
        command.Parameters.AddWithValue("@path", product.Path ?? "");
        command.Parameters.AddWithValue("@siteName", product.SiteName ?? "");
        command.Parameters.AddWithValue("@serviceName", product.ServiceName ?? "");
        command.Parameters.AddWithValue("@backupPath", product.BackupPath ?? "");
        command.Parameters.AddWithValue("@currentVersion", product.CurrentVersion ?? "");
        command.Parameters.AddWithValue("@productName", product.ProductName ?? "");
        command.ExecuteNonQuery();
    }
    
    public List<Product> LoadProducts()
    {
        var products = new List<Product>();
        
        using var connection = new SqliteConnection($"Data Source={dbPath}");
        connection.Open();
        
        var command = connection.CreateCommand();
        command.CommandText = "SELECT * FROM Products";
        
        using var reader = command.ExecuteReader();
        while (reader.Read())
        {
            products.Add(new Product
            {
                Id = reader.GetString(0),
                Name = reader.GetString(1),
                Type = reader.GetString(2),
                Path = reader.GetString(3),
                SiteName = reader.IsDBNull(4) ? null : reader.GetString(4),
                ServiceName = reader.IsDBNull(5) ? null : reader.GetString(5),
                BackupPath = reader.GetString(6),
                CurrentVersion = reader.GetString(7),
                ProductName = reader.GetString(8)
            });
        }
        
        return products;
    }
    
    public void DeleteProduct(string productId)
    {
        using var connection = new SqliteConnection($"Data Source={dbPath}");
        connection.Open();
        
        var command = connection.CreateCommand();
        command.CommandText = "DELETE FROM Products WHERE Id = @id";
        command.Parameters.AddWithValue("@id", productId);
        command.ExecuteNonQuery();
    }
}

public class IISServiceInfo
{
    public int Id { get; set; }
    public string SiteName { get; set; } = "";
    public long SiteId { get; set; }
    public string State { get; set; } = "";
    public string? PhysicalPath { get; set; }
    public string? Bindings { get; set; }
    public string? ApplicationPool { get; set; }
    public DateTime CollectedTime { get; set; }
    public string CurrentVersion { get; set; } = "";
    public string ProductName { get; set; } = "";
}